package hikari.objects3d;

import com.gooddies.wiring.Wiring;
import hikari.gui.MainWindow;
import hikari.gui.panels.camera.CameraPanel;
import hikari.hcomponents.HComponent;
import hikari.managers.Manager3D;
import hikari.persistence.file.FileSection;
import hikari.preferences.SceneProperties;
import hikari.utils.Utils;
import java.io.IOException;
import java.util.List;
import org.swig.jirr.E_MATERIAL_TYPE;
import org.swig.jirr.IBillboardSceneNode;
import org.swig.jirr.ICameraSceneNode;
import org.swig.jirr.ISceneManager;
import org.swig.jirr.ITexture;
import org.swig.jirr.ITriangleSelector;
import org.swig.jirr.MATERIAL_FLAG;
import org.swig.jirr.aabbox3df;
import org.swig.jirr.camera.BasicCamera;
import org.swig.jirr.dimension2df;

/**
 * @author Dmitry
 */
public class Camera3dObject extends Basic3dObject {

    private BasicCamera cameraNode;
    private static ITexture cameraTexture;
    private IBillboardSceneNode cameraSprite;
    private boolean targetCamera = false;

    public Camera3dObject(ISceneManager sceneManager) {
        super("Camera", true);
        initObject(sceneManager);
    }

    public boolean isTargetCamera() {
        return targetCamera;
    }

    public void setTargetCamera(boolean target) {
        this.targetCamera = target;
    }

//    @Override
//    public vector3df getRotation() {
//        return cameraNode.getRotation();
//    }
//    
    private ITexture getCameraTexture() {
        if (cameraTexture == null) {
            cameraTexture = Wiring.getComponent(Utils.class).loadTextureFromResource("icons/camera.png");
        }
        return cameraTexture;
    }

    private void initObject(ISceneManager sceneManager) {
        BasicCamera cameraSceneNode = sceneManager.addBasicCameraSceneNode(0.5f);
        //cameraSceneNode.getRealCamera().bindTargetAndRotation(true);
        Manager3D manager = Wiring.getComponent(Manager3D.class);
        manager.activateStandardCamera();
        manager.addCamera(cameraSceneNode);
        setMeshSceneNode(cameraSceneNode);
        //getMeshSceneNode().getType();

        cameraNode = cameraSceneNode;
        cameraSprite = sceneManager.addBillboardSceneNode(cameraNode, new dimension2df(2f, 2f));
        cameraSprite.setMaterialTexture(0, getCameraTexture());
        cameraSprite.setMaterialType(E_MATERIAL_TYPE.TRANSPARENT_ALPHA_CHANNEL_REF);
        cameraSprite.setMaterialFlag(MATERIAL_FLAG.EMF_LIGHTING, false);
        cameraSprite.setMaterialFlag(MATERIAL_FLAG.EMF_USE_MIP_MAPS, false);
        cameraSprite.setMaterialFlag(MATERIAL_FLAG.EMF_ZBUFFER, false);
        manager.addAlwaysVisibleBillboard(cameraSprite);
        ITriangleSelector selector = sceneManager.createTriangleSelectorFromBoundingBox(cameraSprite);
        cameraSceneNode.setTriangleSelector(selector);
    }

    @Override
    public aabbox3df getBoundingBox() {
        return null;
    }

    @Override
    public List<HComponent> getEditPanels() {
        List<HComponent> panels = super.getEditPanels();
        CameraPanel panel = Wiring.getComponent(CameraPanel.class);
        panel.initialUpdateFromModel(this);
        panels.add(panel);
        return panels;
    }

    public ICameraSceneNode getRealCameraNode() {
        return cameraNode.getRealCamera();
    }

    public BasicCamera getBasicCameraNode() {
        return cameraNode;
    }

    @Override
    public String objectType() {
        if (isTargetCamera()) {
            return "targetCamera";
        } else {
            return "camera";
        }
    }

    @Override
    public void writeData(FileSection section) throws IOException {
        super.writeData(section);
        float fov = getRealCameraNode().getFOV();
        float near = getRealCameraNode().getNearValue();
        float far = getRealCameraNode().getFarValue();
        float aspect = getRealCameraNode().getAspectRatio();
        FileSection camData = section.createNewSection("cameraData");
        camData.writeFloat("fov", fov);
        camData.writeFloat("near", near);
        camData.writeFloat("far", far);
        camData.writeFloat("aspect", aspect);
        camData.close();
    }

    @Override
    public boolean onRemove() {
        if (!super.onRemove()) {
            return false;
        }

        if (Wiring.getComponent(SceneProperties.class).getMainCamera() == this) {
            Boolean result = Wiring.getComponent(Utils.class).confirm(Wiring.getComponent(MainWindow.class), "Camera removing", "This camera was set as main camera in game. Are you sure you want to remove this camera?");
            if (result == null || result == false) {
                return false;
            }

            Wiring.getComponent(SceneProperties.class).setMainCamera(null);
        }
        Wiring.getComponent(Manager3D.class).removeAlwaysVisibleBillboard(cameraSprite);
        Wiring.getComponent(Manager3D.class).removeCamera(getBasicCameraNode());
        return true;
    }
}
